package com.ygqh.baby.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.foxinmy.weixin4j.util.StringUtil;
import com.ygqh.baby.ao.CodeType;
import com.ygqh.baby.ao.DataStatus;
import com.ygqh.baby.ao.Message;
import com.ygqh.baby.ao.PurchaseStatus;
import com.ygqh.baby.ao.QueryInfo;
import com.ygqh.baby.ao.ResultSet;
import com.ygqh.baby.ao.SubscribeType;
import com.ygqh.baby.mapper.AdminPurchaseDetailMapper;
import com.ygqh.baby.mapper.AdminPurchaseMapper;
import com.ygqh.baby.model.AdminPurchaseDetailInCount;
import com.ygqh.baby.model.wdt.WdtInStockItem;
import com.ygqh.baby.model.wdt.WdtInStockOrder;
import com.ygqh.baby.po.AdminContract;
import com.ygqh.baby.po.AdminContractArrive;
import com.ygqh.baby.po.AdminContractDetail;
import com.ygqh.baby.po.AdminPurchase;
import com.ygqh.baby.po.AdminPurchaseDetail;
import com.ygqh.baby.po.AdminPurchaseDetailExample;
import com.ygqh.baby.po.AdminPurchaseExample;
import com.ygqh.baby.po.WdtQybStockIn;
import com.ygqh.baby.po.WdtQybStockInDetail;
import com.ygqh.baby.po.YgProduct;
import com.ygqh.baby.po.YgSku;
import com.ygqh.baby.po.YgSubscribeMsgDetail;
import com.ygqh.baby.service.AdminContractDetailService;
import com.ygqh.baby.service.AdminContractService;
import com.ygqh.baby.service.AdminPurchaseDetailService;
import com.ygqh.baby.service.AdminPurchaseService;
import com.ygqh.baby.service.WxMpMessageService;
import com.ygqh.baby.service.YgFrameCodeService;
import com.ygqh.baby.service.YgProductService;
import com.ygqh.baby.service.YgSkuService;
import com.ygqh.baby.service.YgSubscribeMsgDetailService;
import com.ygqh.baby.service.task.YgAsynClient;
import com.ygqh.baby.utils.MailUtil;
import com.ygqh.baby.utils.ThreadPool;

@Service
public class AdminPurchaseServiceImpl implements AdminPurchaseService {

	@Autowired
	private AdminPurchaseMapper adminPurchaseMapper;
	@Autowired
	private AdminPurchaseDetailMapper adminPurchaseDetailMapper;
	@Autowired
	private YgFrameCodeService ygFrameCodeService;
	@Autowired
	private AdminPurchaseDetailService adminPurchaseDetailService;
	@Autowired
	private YgAsynClient ygAsynClient;
	@Autowired
	private AdminContractService adminContractService;
	@Autowired
	private AdminContractDetailService adminContractDetailService;
	@Autowired
	private YgSubscribeMsgDetailService ygSubscribeMsgDetailService;
	@Autowired
	private YgSkuService ygSkuService;
	@Autowired
	private YgProductService ygProductService;
	@Autowired
	private ThreadPool threadPool;
	@Autowired
	private WxMpMessageService wxMpMessageService;
	@Autowired
	private MailUtil mailUtil;
	@Value("${mail.to.fahuo}")
	private String fahuo;
	@Value("${promotion.link}")
	protected String promotionLink;

	@Override
	public List<AdminPurchase> find() {
		AdminPurchaseExample example = new AdminPurchaseExample();
		example.createCriteria().andStatusEqualTo(DataStatus.Valid.name());
		return adminPurchaseMapper.selectByExample(example);
	}

	@Override
	public int findCount() {
		AdminPurchaseExample example = new AdminPurchaseExample();
		example.createCriteria().andStatusEqualTo(DataStatus.Valid.name());
		return adminPurchaseMapper.countByExample(example);
	}

	@Override
	public AdminPurchase findById(Long id) {
		return adminPurchaseMapper.selectByPrimaryKey(id);
	}

	@Override
	public int save(AdminPurchase adminPurchase) {
		String code = "J" + ygFrameCodeService.getFrameCode(CodeType.Purchase, new Date(), 2);
		adminPurchase.setPurchaseCode(code);
		BigDecimal arriveAmount = new BigDecimal("0");
		// 循环进货单明细 计算 到货数量
		for (AdminPurchaseDetail detail : adminPurchase.getPurchaseDetail()) {
			arriveAmount = arriveAmount.add(detail.getQuantity());
			detail.setPurchaseCode(code);
		}
		adminPurchase.setArriveAmount(arriveAmount);
		adminPurchaseDetailMapper.insertDetail(adminPurchase.getPurchaseDetail());
		ygAsynClient.syncQybPurchaseOrder(adminPurchase);

		return adminPurchaseMapper.insertSelective(adminPurchase);
	}

	@Override
	public int update(AdminPurchase adminPurchase) {
		// 先清除掉明细
		AdminPurchaseDetailExample example = new AdminPurchaseDetailExample();
		example.createCriteria().andPurchaseCodeEqualTo(adminPurchase.getPurchaseCode()).andStatusEqualTo(DataStatus.Valid.name());
		adminPurchaseDetailMapper.deleteByExample(example);
		BigDecimal arriveAmount = new BigDecimal("0");
		// 循环进货单明细 计算 到货数量
		for (AdminPurchaseDetail detail : adminPurchase.getPurchaseDetail()) {
			arriveAmount = arriveAmount.add(detail.getQuantity());
			detail.setPurchaseCode(adminPurchase.getPurchaseCode());
		}
		adminPurchase.setArriveAmount(arriveAmount);
		adminPurchaseDetailMapper.insertDetail(adminPurchase.getPurchaseDetail());

		return adminPurchaseMapper.updateByPrimaryKeySelective(adminPurchase);
	}

	@Override
	public ResultSet<AdminPurchase> search(QueryInfo queryInfo, String q, Date startDate, Date endDate, String purchaseCode,String contractCode) {
		List<AdminPurchase> list = adminPurchaseMapper.selectSuper(queryInfo, q, startDate, endDate, purchaseCode,contractCode);
		int count = adminPurchaseMapper.countSuper(q, startDate, endDate, purchaseCode,contractCode);
		ResultSet<AdminPurchase> resultSet = new ResultSet<AdminPurchase>(count, list);
		return resultSet;
	}

	@Override
	public int deleteSoft(Long[] ids) {
		Assert.notEmpty(ids);
		AdminPurchaseExample example = new AdminPurchaseExample();
		example.createCriteria().andIdIn(Arrays.asList(ids));
		AdminPurchase record = new AdminPurchase();
		record.setStatus(DataStatus.Delete);

		return adminPurchaseMapper.updateByExampleSelective(record, example);
	}

	@Override
	public int updateLogicCode(AdminPurchase purchase) {
		AdminPurchaseExample example = new AdminPurchaseExample();
		example.createCriteria().andPurchaseCodeEqualTo(purchase.getPurchaseCode()).andStatusEqualTo(DataStatus.Valid.name());
		AdminPurchase record = new AdminPurchase();
		record.setLogisticsCode(purchase.getLogisticsCode());
		record.setExpressCompany(purchase.getExpressCompany());
		record.setRemark(purchase.getRemark());
		record.setPreArriveDate(purchase.getPreArriveDate());
		return adminPurchaseMapper.updateByExampleSelective(record, example);
	}

	@Override
	public int deleteSoft(Long id) {
		return this.deleteSoft(new Long[] { id });
	}

	@Override
	public int saveOrUpdate(AdminPurchase adminPurchase) {
		int r = 0;
		if (adminPurchase.getId() != null) {
			r = this.update(adminPurchase);
		} else {
			r = this.save(adminPurchase);
		}
		return r;
	}

	@Override
	public AdminPurchase findPurchaseByCode(String purchaseCode) {
		return adminPurchaseMapper.selectPurchaseByCode(purchaseCode);
	}

	@Override
	public ResultSet<AdminContractArrive> searchContractArrive(QueryInfo queryInfo, String skuCode, String supplierName, String contractCode, Date startDate,
			Date endDate) {
		List<AdminContractArrive> list = adminPurchaseMapper.selectContractArriveReport(queryInfo, skuCode, supplierName, contractCode, startDate, endDate);
		int count = adminPurchaseMapper.countArrive(skuCode, supplierName, contractCode, startDate, endDate);
		ResultSet<AdminContractArrive> resultSet = new ResultSet<AdminContractArrive>(count, list);
		return resultSet;

	}

	@Override
	public List<Map<String, Object>> selectPruchaseDetailBySku(String skuCode, String contractCode) {
		return adminPurchaseMapper.selectDetailList(skuCode, contractCode);
	}

	@Override
	public List<AdminPurchase> selectPurchaseByContractCode(String contractCode) {

		return adminPurchaseMapper.selectPurchaseByContractCode(contractCode);
	}

	@Override
	public int writeBackWdtPurchaseCode(String purchaseCode, String erpOrderCode) {
		AdminPurchaseExample example = new AdminPurchaseExample();
		example.createCriteria().andPurchaseCodeEqualTo(purchaseCode).andStatusEqualTo(DataStatus.Valid.name());
		AdminPurchase record = new AdminPurchase();
		record.setWdtPurchaseCode(erpOrderCode);
		return adminPurchaseMapper.updateByExampleSelective(record, example);
	}

	@Override
	public int writeBackStorageStatus(WdtInStockOrder item) {
		AdminPurchase purchase = this.findByWdtPurchaseCode(item.getPurchaseNO());
		if (purchase != null) {
			// 获取对应的合同明细
			AdminContract contract = adminContractService.findByCode(purchase.getContractCode());

			List<AdminContractDetail> cDetails = adminContractService.findDetail(contract.getId());
			BigDecimal inStockPrice = new BigDecimal(0);// 此次入库金额
			purchase.setInStockTime(item.getTime());
			BigDecimal totalCount = new BigDecimal(0);// 此次入库数量
			for (WdtInStockItem detail : item.getItemList().getItem()) {
				totalCount = totalCount.add(detail.getQty());
				AdminPurchaseDetail pDetail = purchase.getPurchaseDetail().stream().filter(pd -> pd.getSkuCode().equals(detail.getSkuCode())).findFirst().get();
				pDetail.setInAmount(pDetail.getInAmount().add(detail.getQty()));
				AdminContractDetail cDetail = cDetails.stream().filter(d -> d.getSkuCode().equals(pDetail.getSkuCode())).findFirst().get();
				inStockPrice = inStockPrice.add(cDetail.getPrice().multiply(detail.getQty()));
			}
			purchase.setInStockPrice(purchase.getInStockPrice().add(inStockPrice));
			purchase.setInStockAmount(totalCount.add(purchase.getInStockAmount()));
			purchase.setUpdateTime(new Date());
			purchase.setUpdateBy("system");
			if (purchase.getInStockAmount().compareTo(purchase.getArriveAmount()) >= 0) {
				purchase.setPurchaseStatus(PurchaseStatus.InStock);
			} else {
				purchase.setPurchaseStatus(PurchaseStatus.PartInStock);
			}
			adminPurchaseMapper.updateByPrimaryKeySelective(purchase);

			adminPurchaseDetailService.updateBatch(purchase.getPurchaseDetail());
		}
		return 1;
	}

	@Override
	public int writeBackStorageStatus(WdtQybStockIn item) {
		AdminPurchase purchase = this.findByWdtPurchaseCode(item.getSrcOrderNo());
		if (purchase != null) {
			// 获取对应的合同明细
			AdminContract contract = adminContractService.findByCode(purchase.getContractCode());

			List<AdminContractDetail> cDetails = adminContractService.findDetail(contract.getId());
			BigDecimal inStockPrice = new BigDecimal(0);// 此次入库金额
			purchase.setInStockTime(item.getStockinTime());
			BigDecimal totalCount = new BigDecimal(0);// 此次入库数量
			for (WdtQybStockInDetail detail : item.getDetailsList()) {
				totalCount = totalCount.add(detail.getGoodsCount());

				AdminPurchaseDetail pDetail = purchase.getPurchaseDetail().stream().filter(pd -> pd.getSkuCode().equals(detail.getSpecNo())).findFirst().get();
				pDetail.setInAmount(pDetail.getInAmount().add(detail.getGoodsCount()));

				AdminContractDetail cDetail = cDetails.stream().filter(d -> d.getSkuCode().equals(pDetail.getSkuCode())).findFirst().get();
				inStockPrice = inStockPrice.add(cDetail.getPrice().multiply(detail.getGoodsCount()));
			}
			purchase.setInStockPrice(purchase.getInStockPrice().add(inStockPrice));
			purchase.setInStockAmount(totalCount.add(purchase.getInStockAmount()));
			purchase.setUpdateTime(new Date());
			purchase.setUpdateBy("system");
			if (purchase.getInStockAmount().compareTo(purchase.getArriveAmount()) >= 0) {
				purchase.setPurchaseStatus(PurchaseStatus.InStock);
			} else {
				purchase.setPurchaseStatus(PurchaseStatus.PartInStock);
			}
			adminPurchaseMapper.updateByPrimaryKeySelective(purchase);

			adminPurchaseDetailService.updateBatch(purchase.getPurchaseDetail());
			this.inStockReminder(purchase.getContractCode(), item.getSrcOrderNo(), purchase.getPurchaseCode(), item.getDetailsList());
			this.arrivalNotice(item.getDetailsList());
		}
		return 1;
	}

	/**
	 * 到货通知（用户订阅的一次性通知）
	 * 
	 * @Title: arrivalNotice
	 * @param inDetails
	 *            入参
	 * @return void 返回类型
	 * @author （guohao）
	 * @throws
	 * @date 2017年8月1日 上午10:17:37
	 * @version V1.0
	 */
	private void arrivalNotice(List<WdtQybStockInDetail> inDetails) {
		threadPool.getExecutorService().execute(new Runnable() {

			@Override
			public void run() {

				List<YgSubscribeMsgDetail> sendList = new ArrayList<YgSubscribeMsgDetail>();

				List<YgSubscribeMsgDetail> notSendList = ygSubscribeMsgDetailService.findByType(SubscribeType.InStock, null, null, false);
				Map<Long, List<YgSubscribeMsgDetail>> map = notSendList.stream().collect(Collectors.groupingBy(d -> d.getRelationId()));
				label: for (Entry<Long, List<YgSubscribeMsgDetail>> entry : map.entrySet()) {

					List<YgSku> skus = ygSkuService.find(entry.getKey());
					YgProduct product = ygProductService.findById(entry.getKey());
					for (WdtQybStockInDetail inDetail : inDetails) {
						for (YgSku sku : skus) {
							if (inDetail.getSpecNo().equals(sku.getSkuCode())) {
								entry.getValue().stream().forEach(s -> s.setProductName(product.getProductName()));
								sendList.addAll(entry.getValue());
								continue label;
							}

						}
					}
				}
				Date currentDate = new Date();
				for (YgSubscribeMsgDetail msg : sendList) {

					String content = "亲，您关注的 " + msg.getProductName() + " 已经到货啦，如果还没下单赶快去抢购吧，先买先发呦~~";
					String url = promotionLink + "/product/product.html?productId=" + msg.getRelationId();
					Message result = wxMpMessageService.sendSubscribeMsg(msg.getOpenId(), msg.getSubscribeType().getTitle(), msg.getTemplateId(), url,
							msg.getScene(), content);
					msg.setSendTime(currentDate);
					msg.setRemark(result.getContent());
					if (result.getType().equals(Message.Type.success)) {
						msg.setIsSend(true);
					} else {
						msg.setIsSend(false);
					}
				}

				// 回写发送状态
				ygSubscribeMsgDetailService.updateSendStatusBatch(sendList);
			}
		});

	}

	/**
	 * 合同请款提醒
	 * 
	 * @Title: settlementReminder
	 * @param 入参
	 * @return void 返回类型
	 * @author （guohao）
	 * @throws
	 * @date 2017年7月12日 下午1:50:36
	 * @version V1.0
	 */
	private void inStockReminder(String contractCode, String wdtPurchaseCode, String purchaseCode, List<WdtQybStockInDetail> inDetails) {
		List<AdminPurchaseDetailInCount> list = this.findPurchaseDetailInStockCountByContractCode(contractCode);
		List<AdminPurchaseDetailInCount> pDetails = list.stream().filter(pd -> pd.getPurchaseCode().equals(purchaseCode)).collect(Collectors.toList());
		String settlementReminder = "";

		// List<AdminPurchaseDetailInCount> pDetails = new
		// ArrayList<AdminPurchaseDetailInCount>();
		for (AdminPurchaseDetailInCount pDetail : pDetails) {

			for (WdtQybStockInDetail item : inDetails) {
				if (item.getSpecNo().equals(pDetail.getSkuCode())) {
					pDetail.setInAmount(item.getGoodsCount());
					pDetail.setWdtPurchaseCode(wdtPurchaseCode);
				}
			}
		}

		// 总入库数量
		double sum = list.parallelStream().mapToDouble(pd -> pd.getInAmount().floatValue()).reduce(0, (x, y) -> x + y);
		// 当前入库数量大于合同数量的0.8
		if (list.get(0).getcQuantity().doubleValue() * 0.8 <= sum) {
			settlementReminder = "当前合同采购入库数量已达到采购总数量的80%，可以结算";
		}
		this.sendMailInStockReminder(pDetails, fahuo, settlementReminder);
	}

	private void sendMailInStockReminder(List<AdminPurchaseDetailInCount> pDetails, String to, String settlementReminder) {
		StringBuffer str = new StringBuffer();
		str.append("<html><head><style>.table-d table{ background:#000;font-size:14px} .table-d table td{ background:#FFF} h5{width: auto;margin-right: 20px} .title{display: flex;line-height: 10px}");
		str.append("</style></head><body>");
		str.append("<div><h5>合同编号：" + pDetails.get(0).getContractCode() + "</div></h5>");
		str.append("<div><h5>进货单号：" + pDetails.get(0).getPurchaseCode() + "</div></h5>");
		str.append("<div><h5>旺店通单号：" + pDetails.get(0).getWdtPurchaseCode() + "</div></h5>");
		str.append("<div><h5>物流公司：" + pDetails.get(0).getExpressCompany() + "</div></h5>");
		str.append("<div><h5>物流单号：" + pDetails.get(0).getLogisticsCode() + "</div></h5>");
		str.append("<div><h5>进货单件数：" + pDetails.get(0).getArriveAmount() + "</div></h5>");
		str.append("<div class='table-d'>");
		str.append("<table width='800' border='0' cellspacing='1' cellpadding='0'><tr><td width='15%'>商品编码</td>"
				+ "<td width='15%'>商品名称</td><td width='15%'>颜色</td><td width='15%'>尺码</td>" + "<td width='15%'>入库数量</td><td width='15%'>采购数量</td></tr>");
		for (AdminPurchaseDetailInCount detail : pDetails) {
			str.append("<tr><td>" + detail.getSkuCode() + "</td>");
			str.append("<td>" + detail.getProductName() + "</td>");
			str.append("<td>" + detail.getColor() + "</td>");
			str.append("<td>" + detail.getSizeName() + "</td>");
			str.append("<td>" + detail.getInAmount() + "</td>");
			str.append("<td>" + detail.getQuantity() + "</td>");
			str.append("</tr>");
		}
		str.append("</table>");
		if (!StringUtil.isBlank(settlementReminder)) {
			str.append("</br><div><text  style='color:red'>注意：" + settlementReminder + "</text></div>");
		}
		try {
			mailUtil.sendWithHtml(to.split(","), "进货单【" + pDetails.get(0).getPurchaseCode() + "】入库通知", str.toString());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public AdminPurchase findByWdtPurchaseCode(String purchaseCode) {
		AdminPurchaseExample example = new AdminPurchaseExample();
		example.createCriteria().andWdtPurchaseCodeEqualTo(purchaseCode).andStatusEqualTo(DataStatus.Valid.name());
		List<AdminPurchase> list = adminPurchaseMapper.selectByExample(example);
		if (list != null & list.size() > 0) {
			List<AdminPurchaseDetail> detailList = adminPurchaseDetailService.findByPurchaseCode(list.get(0).getPurchaseCode());
			list.get(0).setPurchaseDetail(detailList);
			return list.get(0);
		}
		return null;
	}

	@Override
	public List<AdminPurchaseDetailInCount> findPurchaseDetailInStockCountByContractCode(String contractCode) {
		return adminPurchaseDetailService.findPurchaseDetailInStockCountByContractCode(contractCode);
	}

	@Override
	public List<AdminContractArrive> selectContractArrive(QueryInfo queryInfo, String skuCode, String supplierName, String contractCode, Date startDate,
			Date endDate) {
		return adminPurchaseMapper.selectContractArriveReport(queryInfo, skuCode, supplierName, contractCode, startDate, endDate);
	}

	@Override
	public List<AdminPurchase> searchPurchase(String q, String purchaseCode) {
		return adminPurchaseMapper.selectPurchase(q,purchaseCode);
		
	}

}
